SQLite学习手册(SQLite在线备份)
一、常用备份:
下面的方法是比较简单且常用的SQLite数据库备份方式,见如下步骤:
1). 使用SQLite API或Shell工具在源数据库文件上加共享锁。
2). 使用Shell工具(cp或copy)拷贝数据库文件到备份目录。
3). 解除数据库文件上的共享锁。
以上3个步骤可以应用于大多数场景,而且速度也比较快,然而却存在一定的刚性缺陷,如:
1). 所有打算在源数据库上执行写操作的连接都不得不被挂起,直到整个拷贝过程结束并释放文件共享锁。
2). 不能拷贝数据到in-memory数据库。
3). 在拷贝过程中,一旦备份数据库所在的主机出现任何突发故障,备份数据库可能会被破坏。
在SQLite中提供了一组用于在线数据库备份的APIs函数(C接口),可以很好的解决上述方法存在的不足。通过该组函数,可以将源数据库中的内容拷贝到另一个数据库,同时覆盖目标数据库中的数据。整个拷贝过程可以以增量的方式完成,在此情况下,源数据库也不需要在整个拷贝过程中都被加锁,而只是在真正读取数据时加共享锁。这样,其它的用户在访问源数据库时就不会被挂起。
二、在线备份APIs简介:
SQLite提供了以下3个APIs函数用于完成此操作,这里仅仅给出它们的基本用法,至于使用细节可以参考SQLite官方网站"APIs Reference"()。
1). 函数sqlite3_backup_init()用于创建sqlite3_backup对象,该对象将作为本次拷贝操作的句柄传给其余两个函数。
2). 函数sqlite3_backup_step()用于数据拷贝,如果该函数的第二个参数为-1,那么整个拷贝过程都将在该函数的一次调用中完成。
3). 函数sqlite3_backup_finish()用于释放sqlite3_backup_init()函数申请的资源,以避免资源泄露。
在整个拷贝过程中如果出现任何错误,我们都可以通过调用目的数据库连接的sqlite3_errcode()函数来获取具体的错误码。此外,如果sqlite3_backup_step()调用失败,由于sqlite3_backup_finish()函数并不会修改当前连接的错误码,因此我们可以在调用sqlite3_backup_finish()之后再获取错误码,从而在代码中减少了一次错误处理。见如下代码示例(来自SQLite官网):
复制代码 代码如下:
/IT之家
IT之家IT之家 This function is used to load the contents of a database file on disk
IT之家IT之家 into the "main" database of open database connection pInMemory, or
IT之家IT之家 to save the current contents of the database opened by pInMemory into
IT之家IT之家 a database file on disk. pInMemory is probably an in-memory database,
IT之家IT之家 but this function will also work fine if it is not.
IT之家IT之家
IT之家IT之家 Parameter zFilename points to a nul-terminated string containing the
IT之家IT之家 name of the database file on disk to load from or save to. If parameter
IT之家IT之家 isSave is non-zero, then the contents of the file zFilename are
IT之家IT之家 overwritten with the contents of the database opened by pInMemory. If
IT之家IT之家 parameter isSave is zero, then the contents of the database opened by
IT之家IT之家 pInMemory are replaced by data loaded from the file zFilename.
IT之家IT之家
IT之家IT之家 If the operation is successful, SQLITE_OK is returned. Otherwise, if
IT之家IT之家 an error occurs, an SQLite error code is returned.
IT之家/
int loadOrSaveDb(sqlite3 IT之家pInMemory, const char IT之家zFilename, int isSave){
int rc; /IT之家 Function return code IT之家/
sqlite3 IT之家pFile; /IT之家 Database connection opened on zFilename IT之家/
sqlite3_backup IT之家pBackup; /IT之家 Backup object used to copy data IT之家/
sqlite3 IT之家pTo; /IT之家 Database to copy to (pFile or pInMemory) IT之家/
sqlite3 IT之家pFrom; /IT之家 Database to copy from (pFile or pInMemory) IT之家/
/IT之家 Open the database file identified by zFilename. Exit early if this fails
IT之家IT之家 for any reason. IT之家/
rc = sqlite3_open(zFilename, &pFile);
if( rc==SQLITE_OK ){
/IT之家 If this is a 'load' operation (isSave==0), then data is copied
IT之家IT之家 from the database file just opened to database pInMemory.
IT之家IT之家 Otherwise, if this is a 'save' operation (isSave==1), then data
IT之家IT之家 is copied from pInMemory to pFile. Set the variables pFrom and
IT之家IT之家 pTo accordingly. IT之家/
pFrom = (isSave ? pInMemory : pFile);
pTo = (isSave ? pFile : pInMemory);
/IT之家 Set up the backup procedure to copy from the "main" database of
IT之家IT之家 connection pFile to the main database of connection pInMemory.
IT之家IT之家 If something goes wrong, pBackup will be set to NULL and an error
IT之家IT之家 code and message left in connection pTo.
IT之家IT之家
IT之家IT之家 If the backup object is successfully created, call backup_step()
IT之家IT之家 to copy data from pFile to pInMemory. Then call backup_finish()
IT之家IT之家 to release resources associated with the pBackup object. If an
IT之家IT之家 error occurred, then an error code and message will be left in
IT之家IT之家 connection pTo. If no error occurred, then the error code belonging
IT之家IT之家 to pTo is set to SQLITE_OK.
IT之家/
pBackup = sqlite3_backup_init(pTo, "main", pFrom, "main");
if( pBackup ){
(void)sqlite3_backup_step(pBackup, -1);
(void)sqlite3_backup_finish(pBackup);
}
rc = sqlite3_errcode(pTo);
}
/IT之家 Close the database connection opened on database file zFilename
IT之家IT之家 and return the result of this function. IT之家/
(void)sqlite3_close(pFile);
return rc;
}
三、高级应用技巧:
在上面的例子中,我们是通过sqlite3_backup_step()函数的一次调用完成了整个拷贝过程。该实现方式仍然存在之前说过的挂起其它写访问连接的问题,为了解决该问题,这里我们将继续介绍另外一种更高级的实现方式--分片拷贝,其实现步骤如下:
1). 函数sqlite3_backup_init()用于创建sqlite3_backup对象,该对象将作为本次拷贝操作的句柄传给其余两个函数。
2). 函数sqlite3_backup_step()被调用用于拷贝数据,和之前方法不同的是,该函数的第二个参数不再是-1,而是一个普通的正整数,表示每次调用将会拷贝的页面数量,如5。
3). 如果在函数sqlite3_backup_step()调用结束后,仍然有更多的页面需要被拷贝,那么我们将主动休眠250ms,然后再重复步骤2).
4). 函数sqlite3_backup_finish()用于释放sqlite3_backup_init()函数申请的资源,以避免资源泄露。
在上述步骤3)中我们主动休眠250ms,此期间,该拷贝操作不会在源数据库上持有任何读锁,这样其它的数据库连接在进行写操作时亦将不会被挂起。然而在休眠期间,如果另外一个线程或进程对源数据库进行了写操作,SQLite将会检测到该事件的发生,从而在下一次调用sqlite3_backup_step()函数时重新开始整个拷贝过程。唯一的例外是,如果源数据库不是in-memory数据库,同时写操作是在与拷贝操作同一个进程内完成,并且在操作时使用的也是同一个数据库连接句柄,那么目的数据库中数据也将被此操作同时自动修改。在下一次调用sqlite3_backup_step()时,也将不会有任何影响发生。
事实上,在SQLite中仍然提供了另外两个辅助性函数backup_remaining()和backup_pagecount(),其中前者将返回在当前备份操作中还有多少页面需要被拷贝,而后者将返回本次操作总共需要拷贝的页面数量。显而易见的是,通过这两个函数的返回结果,我们可以实时显示本次备份操作的整体进度,计算公式如下:
Completion = 100% IT之家 (pagecount() - remaining()) / pagecount()
见以下代码示例(来自SQLite官网):
复制代码 代码如下:
/IT之家
IT之家IT之家 Perform an online backup of database pDb to the database file named
IT之家IT之家 by zFilename. This function copies 5 database pages from pDb to
IT之家IT之家 zFilename, then unlocks pDb and sleeps for 250 ms, then repeats the
IT之家IT之家 process until the entire database is backed up.
IT之家IT之家
IT之家IT之家 The third argument passed to this function must be a pointer to a progress
IT之家IT之家 function. After each set of 5 pages is backed up, the progress function
IT之家IT之家 is invoked with two integer parameters: the number of pages left to
IT之家IT之家 copy, and the total number of pages in the source file. This information
IT之家IT之家 may be used, for example, to update a GUI progress bar.
IT之家IT之家
IT之家IT之家 While this function is running, another thread may use the database pDb, or
IT之家IT之家 another process may access the underlying database file via a separate
IT之家IT之家 connection.
IT之家IT之家
IT之家IT之家 If the backup process is successfully completed, SQLITE_OK is returned.
IT之家IT之家 Otherwise, if an error occurs, an SQLite error code is returned.
IT之家/
int backupDb(
sqlite3 IT之家pDb, /IT之家 Database to back up IT之家/
const char IT之家zFilename, /IT之家 Name of file to back up to IT之家/
void(IT之家xProgress)(int, int) /IT之家 Progress function to invoke IT之家/
){
int rc; /IT之家 Function return code IT之家/
sqlite3 IT之家pFile; /IT之家 Database connection opened on zFilename IT之家/
sqlite3_backup IT之家pBackup; /IT之家 Backup handle used to copy data IT之家/
/IT之家 Open the database file identified by zFilename. IT之家/
rc = sqlite3_open(zFilename, &pFile);
if( rc==SQLITE_OK ){
/IT之家 Open the sqlite3_backup object used to accomplish the transfer IT之家/
pBackup = sqlite3_backup_init(pFile, "main", pDb, "main");
if( pBackup ){
/IT之家 Each iteration of this loop copies 5 database pages from database
IT之家IT之家 pDb to the backup database. If the return value of backup_step()
IT之家IT之家 indicates that there are still further pages to copy, sleep for
IT之家IT之家 250 ms before repeating. IT之家/
do {
rc = sqlite3_backup_step(pBackup, 5);
xProgress(
sqlite3_backup_remaining(pBackup),
sqlite3_backup_pagecount(pBackup)
);
if( rc==SQLITE_OK || rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
sqlite3_sleep(250);
}
} while( rc==SQLITE_OK || rc==SQLITE_BUSY || rc==SQLITE_LOCKED );
/IT之家 Release resources allocated by backup_init(). IT之家/
(void)sqlite3_backup_finish(pBackup);
}
rc = sqlite3_errcode(pFile);
}
/IT之家 Close the database connection opened on database file zFilename
IT之家IT之家 and return the result of this function. IT之家/
(void)sqlite3_close(pFile);
return rc;
}
相关热词:
本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供用于网络技术学习参考,学习中请遵循相关法律法规!
本文地址: https://v30.fanwenzhu.com/sql/sqlite/8702.shtml
相关文章
热门TAG
win10 ecshop 主机 阿里云 解决 配置 C# C++ 解析 SQL语句 命令 Go语言 方法 CSS3 HTML5 CSS win7 MSSQL 服务器配置 IIS7.5 IIS7 IIS6 IIS CentOS 7 Linux oracle数据库 oracle phpcms discuz discuz教程最新文章
-
sqlite只通过文件锁就可以
时间:2021-01-23
-
返回的是一个SQLiteDatabas
时间:2021-01-23
-
只不过它是OC方式封装了
时间:2021-01-23
-
应该增加autoincrementcreate
时间:2021-01-23
-
如果没有就从Bundle中把数
时间:2021-01-23
-
Linux 部署ASP.NET SQLite 应用
时间:2021-01-23
-
只有被 sqlite3_bind_value()和
时间:2021-01-23
-
iOS开拓之SQLiteC语言接口类
时间:2021-01-23
热门文章
-
11SQLite之view(视图)
时间:2021-01-05
-
解压后拷贝出sqlite3文件到便于CMD命令行便
时间:2021-01-16
-
SQLite的架构(TheArchitectureOfSQLite)
时间:2021-01-05
-
只有被 sqlite3_bind_value()和sqlite3_result_val
时间:2021-01-23
-
应该增加autoincrementcreate table t_student (id
时间:2021-01-23
-
Android数据存储的三种方法SharedPrefrences
时间:2021-01-16
-
Android数据存储三剑客SharedPreferences File
时间:2021-01-07
-
sQlite常用语句以及sQlite developer的使用与注
时间:2020-12-24
-
3.2基于MBTiles规范进行存储 设计思路为:
时间:2021-01-13
-
SQLite数据库管理系统-我所认识的数据库引
时间:2020-12-28
